/*************************************************
Author: will
Date: 10/11/2012
Description:
Notes:
*************************************************/

#ifndef __CEquipConfig_h__
#define __CEquipConfig_h__

#include "commerrno.h"
#include "commclass.h"
#include "CTSizeString.h"
#include "CTHashObjectMgr.h"
#include "../item/CDropItemSubType.h"
#include "../common/CRandom.h"

class pb_cfg_equip_pb_cfg_refine_and_bless_unit;
class CEquipConfigData
{
public:
    enum EQUIP_REQUEST_CAREER
    {
        EQUIP_REQUEST_CAREER_NONE = 0,      //无要求
        EQUIP_REQUEST_CAREER1 = CAREER_1,   //魔斗士
        EQUIP_REQUEST_CAREER2 = CAREER_2,   //魔法师
        EQUIP_REQUEST_CAREER3 = CAREER_3,   //魔猎手
        EQUIP_REQUEST_CAREER4 = CAREER_4,   //魔斗士
    };

	CEquipConfigData()
    {
	}

	virtual ~CEquipConfigData()
    {
	}

public:
	unsigned short _usEquipConfigID;
    CTSizeString<DROP_ITEM_CFG_SUBTYPE_STR_LEN> _szDropItemSubType;
    unsigned char _ucEquipLevel;    //装备等级 (ENUM_EQUIP_LEVEL, 装备品质指标)
    short _usUseLevel;              //使用装备需要的主角等级
    unsigned char _ucEquipPos;      //装备位置
    unsigned char _ucCareerType;    //职业限制

    unsigned int  _uiGoldBuyPrice;      //金币购买价格
    unsigned int  _uiSilverSellPrice;  	//银币卖出价格
    unsigned int  _uiSilverBuyPrice;  	//银币购买价格

    unsigned char  _ucBaseAttrType1;     //基础属性1
    unsigned int   _uiBaseAttrValue1;    //基础属性值1
    unsigned short _usAttrStrthenValue1; //强化提升值
    unsigned char  _ucBaseAttrType2;     //基础属性2
    unsigned int   _uiBaseAttrValue2;    //基础属性值2
    unsigned short _usAttrStrthenValue2; //强化提升值

    unsigned char _ucSuitID;        //套装属性ID
    unsigned int  _uiBaseFightCap;  //基础战斗力

    unsigned char  _uicCrystalHoleNum;   //魔晶位
    unsigned char  _ucCrystalPermLevel;  //可镶嵌魔晶的最高等级(可以等于这个等级)
    unsigned short _usScrollId;          //制造卷轴ID
    unsigned int   _uiInstanceType;  //缺省的掉落关卡类型
    unsigned int   _uiInstanceId;    //缺省的掉落关卡ID

    int _iRefineAttrCount;              //洗练附加属性位数量
    int _iRefineUseMaterial;            //洗练所使用的材料ID
    int _iMaxBlessLevel;                //祝福属性等级上限

    bool               _bCanAutoSellInIns;  //在副本中是否可以自动出售
};

class CEquipSuiteCfg
{
public:
	CEquipSuiteCfg()
    {
	}

	virtual ~CEquipSuiteCfg()
    {
	}

public:
	unsigned char _ucSuiteId;
	unsigned char _ucSuiteAttrType1;
	unsigned int  _uiSuiteAttrValue1;
	unsigned char _ucSuiteAttrType2;
	unsigned int  _uiSuiteAttrValue2;
	unsigned char _ucSuiteAttrType3;
	unsigned int  _uiSuiteAttrValue3;
};

class CStrengthCfgKey
{
public:
	unsigned short _usEquipLevel;  //当前强化价格跟装备等级无关
	unsigned short _usCurStrengthLevel;
    bool operator==(const CStrengthCfgKey& stKey) const
    {
        return (_usCurStrengthLevel == stKey._usCurStrengthLevel);
    }
};

namespace __gnu_cxx
{
    template<> struct hash<CStrengthCfgKey>
    {
        size_t operator()(const CStrengthCfgKey & x) const
        {
            return (x._usCurStrengthLevel);
        }
    };
}

class CEquipStrengthCfg
{
public:
	CEquipStrengthCfg()
    {
	}

	virtual ~CEquipStrengthCfg()
    {
	}

	CStrengthCfgKey _stKey;
	int _iStrengthPrice;
	int _iSellPrice;
};


class CCystalPotentialCfg
{
public:
    CCystalPotentialCfg()
    {        
        Clear();
    }

    void Clear ()
    {
        _iUpgradeExp = 0;
        _iCoff = 0;
    }
    
    int _iUpgradeExp;   //升级所需的经验(累计值)
    int _iCoff;
};


class CEquipConfig
{
public:
    typedef CTLib::CTHashObjectMgr<unsigned short, CEquipConfigData> T_EQUIP_CONFIG_HASH;
    typedef CTLib::CTHashObjectMgr<unsigned short, CEquipSuiteCfg>    T_EQUIP_SUITE_HASH;
    typedef CTLib::CTHashObjectMgr<CStrengthCfgKey, CEquipStrengthCfg>  T_EQUIP_STRENGTH_HASH;
	typedef CTLib::CTArray<unsigned char,  EQUIP_POS_MAX + 1> T_EQUIP_PRICE_COEF_ARRAY;

	CEquipConfig()
    {
		_stEquipPriceCoef.m_iUsedCount = EQUIP_POS_MAX + 1;
		_stEquipPriceCoef[EQUIP_POS_HELMET] = 7;    //头盔
		_stEquipPriceCoef[EQUIP_POS_CLOTH]	= 6;    //衣服
		_stEquipPriceCoef[EQUIP_POS_WEAPON]	= 15;   //武器
		_stEquipPriceCoef[EQUIP_POS_SHOES]	= 7;    //鞋子
		_stEquipPriceCoef[EQUIP_POS_NECKLACE] = 8;	//项链
		_stEquipPriceCoef[EQUIP_POS_RING] = 8;		//戒指
		_stEquipPriceCoef[EQUIP_POS_AMULET] = 5;	//护符
		_stEquipPriceCoef[EQUIP_POS_SEAL] = 5;      //纹章

        _stPotential.m_iUsedCount = MAX_CRYSTAL_POTENTIAL_LEVEL;
        for (int i = 0; i < _stPotential.Size(); i++)
        {
            _stPotential[i].Clear();
        }

        _ucMaxPotentialLevel = 0;
	}

	virtual ~CEquipConfig()
    {
	}

    static int CountSize()
    {
        return T_EQUIP_CONFIG_HASH::CountSize(MAX_EQUIP_CONFIG_COUNT)
			+ T_EQUIP_SUITE_HASH::CountSize(MAX_EQUIP_SUITE_CFG_COUNT)
			+ T_EQUIP_STRENGTH_HASH::CountSize(MAX_ROLE_LEVEL*EQUIP_LEVEL_MAX)
            + CDropItemSubTypeConfig::CountSize(MAX_EQUIP_CONFIG_COUNT);
    }

    int Init(const char* sBuff)
	{
		/* warn:  调用者保证buff足够大,  Init内部未作判断。
				 空间过小会导致内存访问越界*/
        int iRet = 0;
        int iOffset = 0;
        iRet = _stEquipConfigHash.Init(sBuff + iOffset, MAX_EQUIP_CONFIG_COUNT);
        CHECK_RETURN(iRet);
        iOffset += T_EQUIP_CONFIG_HASH::CountSize(MAX_EQUIP_CONFIG_COUNT);

        iRet = _stEquipSuiteHash.Init(sBuff + iOffset, MAX_EQUIP_SUITE_CFG_COUNT);
        CHECK_RETURN(iRet);
        iOffset += T_EQUIP_SUITE_HASH::CountSize(MAX_EQUIP_SUITE_CFG_COUNT);

        iRet = _stEquipStrengthHash.Init(sBuff + iOffset, MAX_ROLE_LEVEL*EQUIP_LEVEL_MAX);
        CHECK_RETURN(iRet);
        iOffset += T_EQUIP_STRENGTH_HASH::CountSize(MAX_ROLE_LEVEL*EQUIP_LEVEL_MAX);

        iRet = _stDropItemSubTypeConfig.Init(sBuff + iOffset, MAX_EQUIP_CONFIG_COUNT);
        CHECK_RETURN(iRet);
        iOffset += CDropItemSubTypeConfig::CountSize(MAX_EQUIP_CONFIG_COUNT);
		return 0;
	}

    int AddConfigData(CEquipConfigData& stConfigData)
    {
        int iIndex = _stEquipConfigHash.HashAlloc(stConfigData._usEquipConfigID);
        if (iIndex < 0)
        {
            CT_ERROR(("equip config full"));
            return RET_SYSTEM_FAIL;
        }

        _stEquipConfigHash[iIndex] = stConfigData;
        if (stConfigData._szDropItemSubType.GetDataLen() > 0)
        {
            CDropItemSubTypeConfigData stItemDropSubTypeData;
            stItemDropSubTypeData._iItemID = stConfigData._usEquipConfigID;
            int iRet = _stDropItemSubTypeConfig.AddSubType(stConfigData._szDropItemSubType, stItemDropSubTypeData);
            CHECK_RETURN(iRet);
        }
        return 0;
    }

    int GetConfigData(unsigned short usEquipConfigID, CEquipConfigData& stConfigData)
    {
        int iIndex = _stEquipConfigHash.HashFind(usEquipConfigID);
        if (iIndex < 0)
        {
            return ERROR_EQUIP_NO_CONFIG;
        }

        stConfigData = _stEquipConfigHash[iIndex];

        return 0;
    }

    int GetConfigData(CDropItemSubTypeConfigData::T_DROP_ITEM_SUBTYPE_CONFIG_KEY& szKey,
                        CEquipConfigData& stConfigData)
    {
        int iRet = 0;
        CDropItemSubTypeConfigData stItemDropSubTypeData;
        iRet = _stDropItemSubTypeConfig.GetRandomData(szKey, stItemDropSubTypeData);
        CHECK_RETURN(iRet);
        unsigned short _usEquipConfigID = (unsigned short)stItemDropSubTypeData._iItemID;
        return GetConfigData(_usEquipConfigID, stConfigData);
    }

    int AddSuiteCfg(CEquipSuiteCfg& stConfigData)
	{
        int iIndex = _stEquipSuiteHash.HashAlloc(stConfigData._ucSuiteId);
        if (iIndex < 0)
        {
            CT_ERROR(("equip suite config full"));
            return RET_SYSTEM_FAIL;
        }

        _stEquipSuiteHash[iIndex] = stConfigData;
        return 0;
    }

    int GetSuiteConfig(unsigned char ucSuiteID, CEquipSuiteCfg & stConfigData)
    {
        int iIndex = _stEquipSuiteHash.HashFind(ucSuiteID);
        if (iIndex < 0)
        {
            return ERROR_EQUIP_NO_CONFIG;
        }

        stConfigData = _stEquipSuiteHash[iIndex];

        return 0;
    }


    int AddStrengthCfg(CEquipStrengthCfg & stConfigData)
	{

        int iIndex = _stEquipStrengthHash.HashAlloc(stConfigData._stKey);
        if (iIndex < 0)
        {
            CT_ERROR(("equip strength config full"));
            return RET_SYSTEM_FAIL;
        }

        _stEquipStrengthHash[iIndex] = stConfigData;
        return 0;
    }

    int GetStrengthConfig(CStrengthCfgKey & stKey, CEquipStrengthCfg & stConfigData)
    {
        int iIndex = _stEquipStrengthHash.HashFind(stKey);
        if (iIndex < 0)
        {
            return ERROR_EQUIP_NO_CONFIG;
        }

        stConfigData = _stEquipStrengthHash[iIndex];

        return 0;
    }

	int GetScorllEquipId (unsigned short usScrollId, unsigned short & usEquipCfgId)
	{
		usEquipCfgId = 0;
		for (int index = _stEquipConfigHash.GetHeadIndex();
			index >= 0; index = _stEquipConfigHash.GetNextIndex(index))
		{
			if (_stEquipConfigHash[index]._usScrollId == usScrollId)
			{
				usEquipCfgId = _stEquipConfigHash[index]._usEquipConfigID;
				return 0;
			}
		}

		return ERROR_SCROLL_NO_EQUIP;
	}

    int GetPotentialCoff (unsigned char ucLevel)
    {
        if (ucLevel > MAX_CRYSTAL_POTENTIAL_LEVEL || ucLevel <= 0)
        {
            return 0;
        }

        return (_stPotential[ucLevel - 1]._iCoff / COMM_MOD);        
    }

    int GetPotenLevelUpExp (unsigned char ucLevel)
    {
        if (ucLevel > MAX_CRYSTAL_POTENTIAL_LEVEL || ucLevel <= 0)
        {
            return 0;
        }

        return (_stPotential[ucLevel - 1]._iUpgradeExp);
    }

    int AddPotentialCfg (unsigned char ucLevel, CCystalPotentialCfg & stCfg)
    {
        if (ucLevel > MAX_CRYSTAL_POTENTIAL_LEVEL || ucLevel <= 0 || stCfg._iCoff <= 0 || stCfg._iUpgradeExp < 0)
        {
            return ERROR_WRONG_POTENTIAL_CONFIG;
        }

        if (0 == stCfg._iUpgradeExp)
        {
            _ucMaxPotentialLevel = ucLevel;
        }

        //保证经验是有效的
        if (ucLevel != _ucMaxPotentialLevel
            && stCfg._iUpgradeExp <= 0)
        {
            return ERROR_WRONG_POTENTIAL_CONFIG;
        }
        
        _stPotential[ucLevel - 1] = stCfg;        

        return 0;
    }

public:
	T_EQUIP_PRICE_COEF_ARRAY _stEquipPriceCoef;
    T_EQUIP_CONFIG_HASH    _stEquipConfigHash;
public:
	 T_EQUIP_SUITE_HASH     _stEquipSuiteHash;
	 T_EQUIP_STRENGTH_HASH  _stEquipStrengthHash;
     CDropItemSubTypeConfig _stDropItemSubTypeConfig;
     CTArray<CCystalPotentialCfg, MAX_CRYSTAL_POTENTIAL_LEVEL> _stPotential;     
     unsigned char _ucMaxPotentialLevel;
};

class CRefineAndBlessConfig
{
public:
    typedef CTArray<int, MAX_EQUIP_REFINE_LEVEL> T_ATTR_VALUES;

    CRefineAndBlessConfig()
    {
        //_astRefineAttrValues.m_iUsedCount = _astRefineAttrValues.GetCount();

        _astRefineAttrChange.m_iUsedCount = _astRefineAttrChange.GetCount();
        for (int i = 0; i < _astRefineAttrChange.Size(); ++i)
        {
            _astRefineAttrChange[i] = 0;
        }

        _astBlessAttrValues.m_iUsedCount = _astBlessAttrValues.GetCount();
        for (int i = 0; i < _astBlessAttrValues.Size(); ++i)
        {
            _astBlessAttrValues[i] = 0;
        }

        _astBlessNeedPoint.m_iUsedCount = _astBlessNeedPoint.GetCount();
        for (int i = 0; i < _astBlessNeedPoint.Size(); ++i)
        {
            _astBlessNeedPoint[i] = 0;
        }

    }

    int AddConfig(const pb_cfg_equip_pb_cfg_refine_and_bless_unit & stCfgUnit);

    CTArray<T_ATTR_VALUES, MAX_EQUIP_REFINE_ATTR> _astRefineAttrValues; //洗练属性值
    CTArray<unsigned char, MAX_EQUIP_REFINE_ATTR> _astRefineAttrChange; //洗练属性对照表
    CRandomSet<MAX_EQUIP_REFINE_ATTR>             _stRefineAttrDrop;   //洗练等级掉落
    CRandomSet<MAX_EQUIP_REFINE_LEVEL>            _stRefineLevelDrop;    //洗练属性掉落
    int                     _iRefineNeedGold;       //洗练花费
    int                     _iRefineEnableMaxLevel; //洗练激活时的最大属性等级
    int                     _iRefineUseSilverPerAttr; //洗练时每属性消耗的银币数

    int                     _iBlessUseGold;         //祝福消耗符石
    CTArray<int, MAX_EQUIP_BLESS_ROLE_COUNT>    _astBlessRate; //祝福概率，每次祝福roll MAX_EQUIP_BLESS_ROLE_COUNT次属性，每次属性出现的概率不同
    int                     _iBlessFirstHasAttrCount;       //首次祝福的属性最大数量

    CTArray<int, MAX_EQUIP_BLESS_LEVEL> _astBlessAttrValues;    //祝福等级对应的属性值
    CTArray<int, MAX_EQUIP_BLESS_LEVEL> _astBlessNeedPoint;     //祝福升级所需要的祝福点
};

#endif // __CEquipConfig_h__

